package cn.hwm.proxy.rpcdemo;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.net.Socket;

/**
 * rpc客户端
 */
public class RpcFrameClient {

    public static <T> T getRemoteProxy(Class<?> serviceInterface, InetSocketAddress addr) {
        return (T) Proxy.newProxyInstance(RpcFrameClient.class.getClassLoader(), new Class<?>[]{serviceInterface}, new ProxyClient(serviceInterface, addr));
    }

    private static class ProxyClient implements InvocationHandler {

        private final Class<?> serviceInterface;
        private final InetSocketAddress addr;

        public ProxyClient(Class<?> serviceInterface, InetSocketAddress addr) {
            this.serviceInterface = serviceInterface;
            this.addr = addr;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

            Socket socket = new Socket();
            socket.connect(addr);
            try (
                    ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
                    ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream())
            ) {
                outputStream.writeUTF(serviceInterface.getName());
                outputStream.writeUTF(method.getName());
                outputStream.writeObject(method.getParameterTypes());
                outputStream.writeObject(args);
                return inputStream.readObject();
            } finally {
                socket.close();
            }
        }
    }

}
